import { useEffect } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import * as CANNON from "cannon-es";

import { CannonEsDebuggerPro } from "@vladkrutenyuk/cannon-es-debugger-pro";
function App() {
  useEffect(() => {
    // 创建世界
    const scene = new THREE.Scene();
    // 创建相机
    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000
    );
    // 设置相机位置
    camera.position.z = 20;
    camera.position.x = 0;
    camera.position.y = 10;
    camera.lookAt(0, 20, 0); // 设置相机朝向

    const root = new THREE.Group();
    scene.add(root); // 将根节点添加到场景中

    // 创建两个数组更新物理世界和threejs世界
    const cannonBodies = [];
    const threeObjects = [];

    // 创建物理世界
    const world = new CANNON.World();
    // 允许休眠
    world.allowSleep = true;

    const color = 0xe60c0c; // or 'rgb(228, 14, 88)', '#e60c0c', 'red'
    const offset = 0.009;
    const cannonDebugger = new CannonEsDebuggerPro(root, world, color, offset);

    // 物理世界分组
    const group1 = 1; // 物理世界分组1
    const group2 = 2; // 物理世界分组2
    const group3 = 4; // 物理世界分组3
    const group4 = 8; // 物理世界分组4

    {
      // 设置重力
      world.gravity.set(0, -9.82, 0); // m/s²

      // 添加物理材质
      const boxMaterial = new CANNON.Material("boxMaterial"); // 创建材质
      boxMaterial.friction = 0.9; // 摩擦力
      // boxMaterial.restitution = 0.9; // 弹性

      // 添加光滑物理材质
      const boxSlipperyMaterial = new CANNON.Material("boxSlipperyMaterial");
      boxSlipperyMaterial.friction = 0; // 摩擦力

      // 添加弹性物理材质
      const boxElasticityMaterial = new CANNON.Material(
        "boxElasticityMaterial"
      );
      boxElasticityMaterial.friction = 0; // 摩擦力
      boxElasticityMaterial.restitution = 0.9; // 弹性

      {
        let shapeSize = 0.3; // 物体大小
        const boxShape = new CANNON.Particle(); 

        // 创建threejs物体
        const geometry = new THREE.SphereGeometry(shapeSize, 32, 32);
        const material = new THREE.MeshBasicMaterial({
          color: 0xffffff,
        });

        let arr = new Array(15).fill("").map(() => new Array(15).fill("")); // 创建二维数组
        
        
        for (let x = 0; x < arr.length; x++) {
          let row = arr[x];

          for (let y = 0; y < row.length; y++) {
            const boxBody = new CANNON.Body({
              mass: 0.5, // 质量
              shape: boxShape, // 物体形状
              position: new CANNON.Vec3(
                x - 15/2,
                10,
                y - 15/2,
            ), // 初始位置
            //   material: boxMaterial, // 使用摩擦力材质
            });
            world.addBody(boxBody);
            arr[x][y] = boxBody; // 将物体添加到数组中
            cannonBodies.push(boxBody);

            {
              const mesh = new THREE.Mesh(geometry, material);
              root.add(mesh); // 将物体添加到场景中

              // 将物理世界和threejs世界的物体添加到数组中
              threeObjects.push(mesh);
            }
            // 物体之间的约束
            {
              // x 约束
              if (x != 0) {
                const constraint = new CANNON.DistanceConstraint(
                  arr[x - 1][y], // 上一个物体
                  arr[x][y], // 当前物体
                  1
                );
                world.addConstraint(constraint); // 添加约束
              }
              // y 约束
              if (y != 0) {
                const constraint = new CANNON.DistanceConstraint(
                  arr[x][y - 1], // 上一个物体
                  arr[x][y], // 当前物体
                 1
                );
                world.addConstraint(constraint); // 添加约束
              }
            }

          }
        }

        {
          const sphereShape = new CANNON.Sphere(5);
          const sphereBody = new CANNON.Body({
            mass: 0, // 质量
            position: new CANNON.Vec3(0, 5, 0), // 初始位置
            material: boxMaterial, // 使用摩擦力材质
            shape: sphereShape, // 物体形状
          });
          world.addBody(sphereBody);

          cannonBodies.push(sphereBody);

          // 创建threejs物体
          const sphereGeometry = new THREE.SphereGeometry(5, 32, 32);
          const sphereMaterial = new THREE.MeshBasicMaterial({
            color: Math.random() * 0xffffff,
          });
          const sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial);
          root.add(sphereMesh); // 将物体添加到场景中
          threeObjects.push(sphereMesh);
        }
      }

      // 添加地面
      {
        // const groundShape = new CANNON.Box(new CANNON.Vec3(5, 0.05, 5));
        // const groundBody = new CANNON.Body({
        //     mass: 0, // 质量为0表示静止物体
        //     position: new CANNON.Vec3(0, -0.5, 0), // 初始位置
        //     material: boxMaterial, // 使用摩擦力材质
        // });
        // groundBody.addShape(groundShape);
        // world.addBody(groundBody);

        // 创建平面
        const planeShape = new CANNON.Plane();
        const planeBody = new CANNON.Body({
          mass: 0, // 质量为0表示静止物体
          position: new CANNON.Vec3(0, 0, 0), // 初始位置
          material: boxMaterial, // 使用摩擦力材质
        });
        // 设置平面的旋转
        planeBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0); // 绕x轴旋转90度
        planeBody.addShape(planeShape);
        world.addBody(planeBody);
      }
    }

    {

      {
        // 创建平面
        const planeShape = new THREE.BoxGeometry(10, 0.1, 10);
        const planeMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff });
        const plane = new THREE.Mesh(planeShape, planeMaterial);
        // 设置平面位置
        plane.position.y = -0.1;
        // 将平面添加到场景中
        scene.add(plane);
      }
    }

    // 创建渲染器
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    // 将渲染器添加到DOM中
    document.getElementById("app").appendChild(renderer.domElement);

    // 添加轨道控制器
    const controls = new OrbitControls(camera, renderer.domElement);
    // 创建坐标辅助器
    const axesHelper = new THREE.AxesHelper(5);
    scene.add(axesHelper); // 将坐标辅助器添加到场景中

    // 创建动画函数
    const animate = function () {
      // 更新物理世界
      world.step(1 / 60); // 60fps
      // 更新threejs世界
      for (let i = 0; i < cannonBodies.length; i++) {
        const body = cannonBodies[i];
        const mesh = threeObjects[i];
        // 更新threejs物体的位置和旋转
        mesh.position.copy(body.position);
        mesh.quaternion.copy(body.quaternion);
      }
      cannonDebugger.update(); // 更新调试器

      // 更新轨道控制器
      controls.update();

      requestAnimationFrame(animate);

      // 渲染场景
      renderer.render(scene, camera);
    };
    // 调用动画函数
    animate();

    return () => {
      // 清除渲染器
      renderer.dispose();
      // 清除场景
      scene.clear();
      // 清除相机
      camera.clear();
      // 清除渲染器DOM
      const app = document.getElementById("app");
      if (app) {
        app.removeChild(renderer.domElement);
      }
    };
  }, []);
  return <div id="app"></div>;
}

export default App;
